<?php

use think\facade\Cache;
use think\facade\Db;
use Webman\Event\Event;
use support\Container;
use Webman\Http\Response;
use support\exception\ValidateException;
use support\Redis;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

/**
 * 数据签名认证
 * @param  array  $data 被认证的数据
 * @return string       签名
 */
function data_auth_sign($data,$screct) {
    //数据类型检测
    if(!is_array($data)){
        $data = (array)$data;
    }
    ksort($data); //排序
    $code = http_build_query($data,$screct); //url编码并生成query字符串
    $sign = sha1($code); //生成签名
    return $sign;
}


/*
 * 生成交易流水号
 * @param char(2) $type
 */
function doOrderSn($type){
	return date('YmdHis') .$type. substr(microtime(), 2, 3) .  sprintf('%02d', rand(0, 99));
}


//上传文件黑名单过滤
function upload_replace($str){
	$farr = ["/php|php3|php4|php5|phtml|pht|/is"];
	$str = preg_replace($farr,'',$str);
	return $str;
}



//随机数
function random($length=10, $type='letter', $convert=0)
{
    $config = array(
        'number'=>'1234567890',
        'letter'=>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
        'string'=>'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789',
        'all'=>'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    );

    if(!isset($config[$type])) $type = 'letter';
    $string = $config[$type];

    $code = '';
    $strlen = strlen($string) -1;
    for($i = 0; $i < $length; $i++){
        $code .= $string[mt_rand(0, $strlen)];
    }
    if(!empty($convert)){
        $code = ($convert > 0)? strtoupper($code) : strtolower($code);
    }
    return $code;
}

//根据键名获取键值
function getItemVal($val,$item_config){
	if(!is_null($val)){
		$str = '';
		foreach(explode(',',$val) as $v){
			foreach(json_decode($item_config,true) as $m){
				if($v == $m['val']){
					$str .= $m['key'].',';
				}
			}
		}
		return rtrim($str,',');
	}
}

//根据键值获取键名
function getValByKey($val,$item_config){
	if($val){
		$str = '';
		foreach(explode(',',$val) as $v){
			foreach(json_decode($item_config,true) as $m){
				if($v == $m['key']){
					$str .= $m['val'].',';
				}
			}
		}
		return rtrim($str,',');
	}
}

//无限极分类转为带有 children的树形select结构
function _generateSelectTree ($data, $pid = 0) {
	$tree = [];
	if ($data && is_array($data)) {
		foreach($data as $v) {
			if($v['pid'] == $pid) {
				$tree[] = [
					'key' => $v['key'],
					'val' => $v['val'],
					'children' => _generateSelectTree($data, $v['val']),
				];
			}
		}
	}
	return $tree;
}

//无限极分类转为带有 children的树形list表格结构
function _generateListTree ($data, $pid = 0,$config=[]) {
	$tree = [];
	if ($data && is_array($data)) {
		foreach($data as $v) {
			if($v[$config[1]] == $pid) {
				$tree[] = array_merge($v,['children' => _generateListTree($data, $v[$config[0]],$config)]);
			}
		}
	}
	return $tree;
}


//获取键值对信息
function getItemData($data){
	$str = in_array(json_encode(array_values($data)),['[]','[[]]']) ? '' : json_encode(array_values($data),320);
	return $str;
}




//钩子函数
function hook($hookname,&$data){
	$path = str_replace('/', '\\',$hookname);
	list($controller,$action) = explode('@',$path);
	$controller = Container::get($controller);
	if (method_exists($controller, $action)) {
		try{
			$response = call_user_func_array([$controller, $action], [&$data]);
		}catch(\Exception $e){
			throw new ValidateException($e->getMessage());
		}
		return $response;
	}
}


function generateRandomString($length) : string {
	$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
	$charactersLength = strlen($characters);
	$randomString = '';

	for ($i = 0; $i < $length; $i++) {
			$randomString .= $characters[rand(0, $charactersLength - 1)];
	}

	return $randomString;
}


function createSignatureNonce()
{
    return generateRandomString(8) . "-" . generateRandomString(4) . "-" . generateRandomString(4) . "-" . generateRandomString(4) . "-" . generateRandomString(12);
}



function updateWavHeader($filePath, $audioDataSize, $sampleRate = 16000, $numChannels = 1, $bitsPerSample = 16) {
	$numSamples = $audioDataSize / ($bitsPerSample / 8);

	// RIFF Chunk
	$chunkID = "RIFF";
	$format = "WAVE";
	$subchunk1ID = "fmt ";
	$subchunk1Size = 16;
	$audioFormat = 1; // PCM
	$byteRate = $sampleRate * $numChannels * ($bitsPerSample / 8);
	$blockAlign = $numChannels * ($bitsPerSample / 8);
	$subchunk2ID = "data";
	$subchunk2Size = $audioDataSize;
	$chunkSize = 4 + (8 + $subchunk1Size) + (8 + $subchunk2Size);

	// 打开文件并写入实际的头部信息
	$file = fopen($filePath, "r+b");
	if ($file === false) {
			throw new Exception("Unable to open file: " . $filePath);
	}

	// 写入 RIFF Chunk
	fwrite($file, $chunkID);
	fwrite($file, pack('V', $chunkSize));
	fwrite($file, $format);

	// 写入 fmt Subchunk
	fwrite($file, $subchunk1ID);
	fwrite($file, pack('V', $subchunk1Size));
	fwrite($file, pack('v', $audioFormat));
	fwrite($file, pack('v', $numChannels));
	fwrite($file, pack('V', $sampleRate));
	fwrite($file, pack('V', $byteRate));
	fwrite($file, pack('v', $blockAlign));
	fwrite($file, pack('v', $bitsPerSample));

	// 写入 data Subchunk
	fwrite($file, $subchunk2ID);
	fwrite($file, pack('V', $subchunk2Size));

	// 关闭文件
	fclose($file);
}



function chatCreateHeader(string $apiKey) : array
{
		$headers = [
				'Expect' => '',  // 空的 Expect 头
				'Accept' => 'text/event-stream;charset=UTF-8',
				'Content-Type' => 'application/json',
				'X-AcA-DataInspection' => 'enable',
				'X-AcA-SSE' => 'enable',
				'x-fag-servicename' => 'aca-chat-send-sse',
				'x-fag-appcode' => 'aca',
				'Authorization' => 'Bearer ' . $apiKey
		];
		return $headers;
}

function chatCreateBody(string $characterId,string $userId,array $messages = [], string $userName = '') : array
    {
        $data = [
            'input' => [
                'messages' => $messages,
                'aca' => [
                    'botProfile' => [
                        'characterId' => $characterId
                    ],
                    'userProfile' => [
                        'userId' => $userId,
                        'userName' => $userName,
                        'basicInfo' => ''
                    ],
                    'scenario' => [
                        'description' => ''
                    ],
                    'context' => [
                        'useChatHistory' => false
                    ]
                ]
            ],
            'parameters' => [
                'incrementalOutput' => true
            ]
        ];

        return $data;
    }




function loadMetaConfigCacheRedis()
{
	$redis_config = Redis::connection("config");
	//阿里云配置
	$aly_config_data = Db::name('ai_speech_aly')->field('name,data')->where(1,1)->select()->toArray();
	$aly_config = [];
	foreach($aly_config_data as $row)
	{
		$aly_config[$row['name']] = $row['data'];
	}
	$redis_config->set("aly_config", json_encode($aly_config) );

	//TTS配置
	$TTS_config_data = Db::name('typetts')->field('appkey,url,type')->where(1,1)->select()->toArray();
	$TTS_config = [];
	foreach($TTS_config_data as $row)
	{
		$TTS_config[$row['type']] = [
			"appkey" => $row['appkey'],
			"url" => $row['url']
		];
	};
	$redis_config->set("TTS_config", json_encode($TTS_config) );

	//STT配置
	$STT_config_data = Db::name('typestt')->field('appkey,url,type')->where(1,1)->select()->toArray();
	$STT_config = [];
	foreach($TTS_config_data as $row)
	{
		$STT_config[$row['type']] = [
			"appkey" => $row['appkey'],
			"url" => $row['url']
		];
	};
	$redis_config->set("STT_config", json_encode($STT_config) );

	//chat配置
	$chat_config_data = Db::name('chat')->field('appkey,type')->where(1,1)->select()->toArray();
	$chat_config = [];
	foreach($chat_config_data as $row)
	{
		$chat_config[$row['type']] = [
			"appkey" => $row['appkey']
		];
	};
	$redis_config->set("chat_config", json_encode($chat_config) );

}



function getConfigByType($type, $key)
{
	switch($type)
	{
		case "tts":
			$redis_config = Redis::connection("config");
			$TTS_config = json_decode($redis_config->get("TTS_config"),true);
			return $TTS_config[$key];
			break;
		case "stt":
			$redis_config = Redis::connection("config");
			$STT_config = json_decode($redis_config->get("STT_config"),true);
			return $STT_config[$key];
			break;
	}
	return false;
}

function isjson($string) {
	json_decode($string);
	return (json_last_error() == JSON_ERROR_NONE);
}


function generateHex($length = 32) {
	if ($length % 2 != 0) {
			throw new InvalidArgumentException("长度必须是偶数，因为每个字节代表两个十六进制字符。");
	}
	
	// 生成二进制数据
	$bytes = random_bytes($length / 2);

	// 转换为十六进制字符串
	$hexString = bin2hex($bytes);

	return $hexString;
}



function getToken($type)
{
	$redis_config = Redis::connection("config");
	$token = $redis_config->get($type . "_token");
	$ExpireTime = $redis_config->get($type . "_ExpireTime");
	if($token && $ExpireTime > time())
	{
		return $token;
	}

	switch($type)
	{
		case "aly":
			$res = createAlyToken();
			if(isset($res->Token))
			{
				$token = $res->Token->Id;
				$ExpireTime = $res->Token->ExpireTime;
				$redis_config->set("aly_token", $token);
				$redis_config->set("aly_ExpireTime", $ExpireTime);
				return $token;
			}else{
				return false;
			}
		break;
		case "paddspeech":
			break;
	}
}


function createAlyToken()
{
	$AccessKeyId =  'LTAI5t7bgDXCNWMmc7DxsfGu';
	$AccessKeySecret = 'U2suDaDDO1q0WOQV3b4JIw6p3nUYhd';
	// 获取当前UTC时间并格式化为 ISO 8601 字符串
	$timestamp = gmdate("Y-m-d\TH:i:s\Z");
	$SignatureNonce = createSignatureNonce();
	$urlPah = 'http://nls-meta.cn-shanghai.aliyuncs.com/';
	$HTTPMethod = "GET";
	$headers = [
			'Accept' => 'application/json',
			'Content-type'=>'application/x-www-form-urlencoded'
	];
	$params = [
			'AccessKeyId'=>$AccessKeyId,
			'Action'    =>'CreateToken',
			'Version'   =>'2019-02-28',
			'Format'    =>'JSON',
			'RegionId'  =>'cn-shanghai',
			'Timestamp' => $timestamp,
			'SignatureMethod' => 'HMAC-SHA1',
			'SignatureVersion' => '1.0',
			'SignatureNonce' => $SignatureNonce
	];
	// 字段排序
	ksort($params, SORT_STRING);

	$encodedParams = [];
	foreach ($params as $key => $value) {
			$encodedKey = urlencode($key);
			$encodedValue = urlencode($value);
			$encodedParams[] = $encodedKey . '=' . $encodedValue;
	}
	// 构建规范化的查询字符串
	$canonicalQueryString = implode('&', $encodedParams);

	$stringToSign = $HTTPMethod . "&" . urlencode('/') . "&" . urlencode($canonicalQueryString);

	$signature = base64_encode( hash_hmac('sha1', $stringToSign, $AccessKeySecret . "&", true) );

	//  对 Base64 编码的结果进行 URL 编码
	$urlEncodedSignature = urlencode($signature);

	$httpUrl = $urlPah . '?Signature=' .$urlEncodedSignature . '&' . $canonicalQueryString;

	$client = new Client([
			'timeout'  => 3.0, // 请求超时设置
	]);
	// 发送 GET 请求
	$response = $client->get($httpUrl);
	// 输出响应体内容
	$responseBody =  $response->getBody();
	return json_decode($responseBody->getContents());
}